<?php
//
// Library file used for simple image/media gallery.
// Used at *.yarpen.cz sites.
// Licensed under the MIT License - see below.
//          http://www.opensource.org/licenses/mit-license.php
//
// This file requires included file "config.php". Modify existing
// one to fit your needs.
//
// Requires php 5.0, php modules: imagick (prefered) 2.0< or gd
//
// Copyright (c) 2009, Petr Vanek <petr@yarpen.cz>
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//
//

require('config.php');
require('gdimage.php');


// Obtain localization
if (strlen(Config::LANG) == 0)
    $lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
else
    $lang = Config::LANG;
$langInclude = 'inc/lang/'.$lang.'.php';
if (!file_exists($langInclude))
{
    $lang = 'en';
    $langInclude = 'inc/lang/en.php';
}

require($langInclude);




// debug
// echo '<p>Error: ' . $_GET["error"] .'</p>';
// echo '<p>Location: ' . $_GET["location"] .'</p>';

// Handle input params.
// It allows only paths under Config::BASE_DIR. All other inputs
// e.g. location=foo/ are skipped.
if (isset($_GET["location"]))
{
    $realLocation = $_GET["location"];
    // check if it begins with base dir
    if (substr( $realLocation, 0, strlen( Config::BASE_DIR ) ) != Config::BASE_DIR )
    {
        $realLocation = Config::BASE_DIR;
    }
    if ($realLocation{strlen($realLocation)-1} != '/')
        $realLocation .= '/';
}
else
    $realLocation = Config::BASE_DIR;


function getDirs($dirName)
{
    $dirs = array();
    $paths = glob($dirName.'*', GLOB_MARK|GLOB_ONLYDIR);

    foreach ($paths as $path)
    {
        $dirs[] = $path;
    }
    return $dirs;
}

function getDirsSortedByDate($dirName)
{
    $paths = glob($dirName.'*', GLOB_MARK|GLOB_ONLYDIR);
    // Sort files by modified time, latest to earliest
    // Use SORT_ASC in place of SORT_DESC for earliest to latest
    array_multisort(
                    array_map('filemtime', $paths),
                    SORT_NUMERIC,
                    SORT_DESC,
                    $paths
                   );

    $ret = array();
    foreach ($paths as $path)
        $ret[$path] = strftime(Config::DATE_DISPLAY_MASK, filemtime($path));

    return $ret;
}

function getFiles($dirName)
{
    $files = array();
    $paths = glob($dirName.'*.*', GLOB_MARK);

    foreach($paths as $path)
    {
        if (is_file($path))
            $files[] = $path;
    }
    return $files;
}

function getNavigation($location)
{
    $dirs = getDirs($location);

    echo '<h3>'. Lang::SUBGALLERIES .'</h3>';

    foreach ($dirs as $i)
    {
        echo '<a href="?location='. $i . '">' . str_replace($location, '', $i) . '</a>';
    }

    if ($location != Config::BASE_DIR)
    {
        $levelUp = implode(explode('/', $location, -2), '/');
        echo '<a href="?location='. $levelUp .'">'. Lang::LEVEL_UP .'</a>';
    }
}

function getBreadcrumbs($location)
{
    echo '<div id="breadcrumbs">';
    echo '<h3>'. Lang::BREADCRUMBS .'</h3>';
    $chunks = explode('/', $location);
    $increment = '';
    foreach($chunks as $chunk)
    {
        if (strlen($chunk) == 0)
            continue;
        $increment .= $chunk . '/';
        echo '<a href="?location=' . $increment . '">' . $chunk . '</a>&nbsp;/&nbsp;';
    }
}


function str_replace_once($needle , $replace , $haystack)
{
    // Looks for the first occurence of $needle in $haystack
    // and replaces it with $replace.
    $pos = strpos($haystack, $needle);
    if ($pos === false) {
        // Nothing found
        return $haystack;
    }
    return substr_replace($haystack, $replace, $pos, strlen($needle));
}

function generateImage($sourceImage, $targetImage, $imageWidth)
{
    $angle = 0;
    $flip = 0;
    if (Config::IMAGE_EXIF_AUTOROTATE && function_exists("exif_read_data"))
    {
        $exif = exif_read_data($sourceImage);
        //echo '<p><pre>';
	//print_r( $exif);
	//echo '</pre></p>';
        $ori = $exif["Orientation"];
	switch($ori)
	{
	    case 1: break;
	    case 2: $flip = 1; break;
	    case 3: $angle = 180; break;
	    case 4: $flip = 2; break;
	    case 5: $flip = 2; $angle = 270; break;
	    case 6: $angle = 270; break;
	    case 7: $flip = 1; $angle = 270; break;
	    case 8: $angle = 90; break;
	}
    }
    // Imagick is prefered way. Compare the code with gd...
    if (class_exists('Imagick'))
    {
        $thumb = new Imagick($sourceImage);
        if ($angle != 0)
        {
            // GD rotates CCW, imagick rotates CW
            $angle = 360 - $angle;
            if (!$thumb->rotateImage(new ImagickPixel(), $angle))
            {
                die('Qook! Cannot autorotate image:'. $targetImage);
            }
        }
        if ($flip != 0)
        {
            switch ($flip)
            {
                case 1: $thumb->flopImage(); break;
                case 2; $thumb->flipImage(); break;
            }
        }
        if (!$thumb->resizeImage($imageWidth, 0, Imagick::FILTER_LANCZOS, 1))
        {
            die('Oook! Cannot resize image: '. $targetImage);
        }
        if (!$thumb->writeImage($targetImage))
        {
            die('Oook! Cannot write image: '. $targetImage);
        }
        $thumb->clear();
        $thumb->destroy();
    }
    else if (function_exists('imagecreatefromjpeg'))
    {
        // rotation with GD is deadly slow. So the lower wuality output
        // with resize-first-then-rotate is acceptable. Imagick is
        // the prefered way.
        $img = new Image($sourceImage);
        $img->resize($imageWidth, 0);
	if ($angle != 0)
	    $img->rotate($angle);
	if ($flip != 0)
	    $img->flip($flip);
	$img->save($targetImage);
    }
    else
    {
        die('Oook! No appropriate image module found. Install Imagick or gd php-extensions.');
    }
    chmod($targetImage, Config::MKFILE_MASK);
}

function generateFile($src, $name)
{
    $fileType = getFileExtension($src);
    // sounds
    if (strpos(Config::MUSIC_EXTENSIONS, $fileType) !== false)
    {
        if (!copy(Config::MUSIC_THUMBNAIL, $name))
            die('Oook! Cannot copy file '. Config::MUSIC_THUMBNAIL . ' into ' . $name);
    }
    // videos
    else if (strpos(Config::VIDEO_EXTENSIONS, $fileType) !== false)
    {
        if (!copy(Config::VIDEO_THUMBNAIL, $name))
            die('Oook! Cannot copy file '. Config::VIDEO_THUMBNAIL . ' into ' . $name);
    }
    else
    {
        if (!copy(Config::BINARY_THUMBNAIL, $name))
            die('Oook! Cannot copy file '. Config::BINARY_THUMBNAIL . ' into ' . $name);
    }
    chmod($name, Config::MKFILE_MASK);
}

function m_mkdir($destination)
{
    if (!mkdir($destination, Config::MKDIR_MASK, true))
    {
        return false;
    }

    $subdir = '';
    foreach(explode('/', $destination) as $node)
    {
        $subdir .= $node . '/';
        // some phpsu instances won't accept mkdir's mask...
        chmod($subdir, Config::MKDIR_MASK);
    }
    return true;
}

function generateItems($location, $destination, $imageWidth)
{
    $source = getFiles($location);
    $target = getFiles($destination);

    if (!file_exists($destination))
    {
        if (!m_mkdir($destination))
        {
            die('Oook! Cannot create directory: '.$destination);
        }
    }
    $ix = 0;
    $changed = false;
    foreach ($source as $src)
    {
        // construct required name: originalname.ext.png
        $name = $destination . basename($src) . '.jpg';

        if (!in_array($name, $target))
        {
            ob_end_flush();
            ?>
            <div id="progressbar">Generating stuff for: <?php echo $name; ?></div>
            <?php

            if (getAllowFile($src))
            {
                generateImage($src, $name, $imageWidth);
            }
            else
            {
                generateFile($src, $name);
            }

            $ix++;
            $changed = true;
            if ($ix >= Config::REFRESH_COUNT)
            {
                refreshJS();
                $ix = 0;
            }

            ob_flush();
            flush();
        }
    }

    if ($changed)
    {
        refreshJS();
    }
}

function refreshJS()
{
    sleep(1);
    echo "<script>window.location.replace(\"" . $_SERVER['PHP_SELF'] . "?" . $_SERVER['QUERY_STRING'] . "\");</script>";
    echo "<a href=\"" . $_SERVER['PHP_SELF'] . "?" . $_SERVER['QUERY_STRING'] . "\">refresh</a>";
    die("it should be redirected automatically...");
}

function getFileExtension($fileName)
{
    // finfo requires php 5.3
//     $fileType = new finfo(FILEINFO_MIME, $display);
//     if (!fileType)
//     {
//         die('Cannot obtain mime type for ' . $display);
//     }
    // workaround for my php version
    $fileInfo = pathinfo($fileName);
    return strtolower($fileInfo["extension"]);
}

function getAllowFile($fileName)
{
    $fileType = getFileExtension($fileName);
    return (strpos(Config::IMAGE_EXTENSIONS, $fileType) !== false);
}

function getFileRepresentation($thumb, $display, $original)
{

    echo '<span class="image">';

    if (!getAllowFile($display))
    {
        // handle non-image files
        echo '<a href="'. $display .'">';
        echo '<img src="'.  $thumb . '" width="' . Config::THUMB_WIDTH . '"/>';
        echo '</a>';
    }
    else
    {
        echo '<a href="'. $display . '" class="thickbox" rel="lightbox[gallery]">';
        echo '<img src="' . $thumb . '" width="' . Config::THUMB_WIDTH . '"/>';
        echo '</a>';
        if (Config::ALLOW_ORIGINAL_IMAGES)
        {
            echo '<a href="'. $original .'" class="original">'. Lang::ORIGINAL .'</a>';
        }
    }
    echo '</span>';
}


function getContent($location)
{
    if (!file_exists($location))
    {
        die('Oook! '.$location. ' doesn\'t exist');
    }

    getSubGalleries($location);
    getGallery($location);
}

function getSubGalleries($location)
{
    $subGalleries = getDirsSortedByDate($location);
    if (count($subGalleries) == 0)
        return;

    echo '<h3>'. Lang::SUBGALLERIES .'</h3>';
    echo '<table class="subgalleries">';
    foreach ($subGalleries as $subGallery => $modDateTime)
    {
        echo '<tr><td>';
        echo '<a href="?location='. $subGallery .'">'. str_replace($location, '', $subGallery) . '</a>';
        echo '</td><td>';
        echo $modDateTime;;
        echo '</td></tr>';
    }
    echo '</table>';
}

function getGallery($location)
{
    $thumbLocation = str_replace_once(Config::BASE_DIR, Config::THUMB_DIR, $location);
    if (!file_exists($thumbLocation))
    {
        generateItems($location, $thumbLocation, Config::THUMB_WIDTH);
    }

    $displayLocation = str_replace_once(Config::BASE_DIR, Config::DISPLAY_DIR, $location);
    if (!file_exists($displayLocation))
    {
        generateItems($location, $displayLocation, Config::DISPLAY_WIDTH);
    }

    $images = getFiles($location);
    if (count($images) == 0)
        return;

    echo '<h3>'. Lang::GALLERY_CONTENT .'</h3>';
    foreach ($images as $image)
    {
        $thumb = $thumbLocation . basename($image) . '.jpg';

        // safe check for missing files
        if (!file_exists($thumb))
        {
            generateItems($location, $thumbLocation, Config::THUMB_WIDTH);
        }

        if (getAllowFile($image))
        {
            $display = $displayLocation . basename($image) . '.jpg';
        }
        else
            $display = $location . basename($image);

        // safe check for missing files
        if (!file_exists($display))
        {
            generateItems($location, $displayLocation, Config::DISPLAY_WIDTH);
        }

        getFileRepresentation($thumb, $display, $image);
    }
}
?>
